# Functions

# prototype
snippet proto
	${1:class_name}.prototype.${2:method_name} = function(${3}) {
		${0}
	};
# Function
snippet fun
	function ${1:function_name}(${2}) {
		${0}
	}
# Anonymous Function
snippet f "" w
	function(${1}) {
		${0}
	}
# Anonymous Function assigned to variable
snippet vaf
	var ${1:function_name} = function(${2}) {
		${0}
	};
# Function assigned to variable
snippet vf
	var ${1:function_name} = function $1(${2}) {
		${0}
	};
# Immediate function
snippet (f
	(function(${1}) {
		${0}
	}(${2}));
# self-defining function
snippet sdf
	var ${1:function_name} = function (${2:argument}) {
		${3}

		$1 = function ($2) {
			${0}
		};
	};

# Flow control

# if
snippet if
	if (${1:true}) {
		${0}
	}
# if ... else
snippet ife
	if (${1:true}) {
		${2}
	} else {
		${0}
	}
# tertiary conditional
snippet ter
	${1:/* condition */} ? ${2:/* if true */} : ${0:/* if false */}
# switch
snippet switch
	switch (${1:expression}) {
		case '${3:case}':
			${4}
			break;
		${0}
		default:
			${2}
	}
# case
snippet case
	case '${1:case}':
		${2}
		break;
	${0}
# try
snippet try
	try {
		${1}
	} catch (${2:e}) {
		${0:/* handle error */}
	}
# try finally
snippet tryf
	try {
		${1}
	} catch (${2:e}) {
		${0:/* handle error */}
	} finally {
		${3:/* be executed regardless of the try / catch result*/}
	}
# throw Error
snippet terr
	throw new Error('${1:error message}')
# return
snippet ret
	return ${0:result};

# Loops

# for loop
snippet for
	for (var ${2:i} = 0, l = ${1:arr}.length; $2 < l; $2++) {
		var ${3:v} = $1[$2];${0:}
	}
# Reversed for loop
snippet forr
	for (var ${2:i} = ${1:arr}.length - 1; $2 >= 0; $2--) {
		var ${3:v} = $1[$2];${0:}
	}
# While loop
snippet wh
	while (${1:/* condition */}) {
		${0}
	}
# Do while loop
snippet do
	do {
		${0}
	} while (${1:/* condition */});
# For in loop
snippet fori
	for (var ${1:prop} in ${2:object}) {
		${0:$2[$1]}
	}

# Objects

# Object Method
snippet :f
	${1:method_name}: function (${2:attribute}) {
		${3}
	},
# hasOwnProperty
snippet has
	hasOwnProperty(${0})
# singleton
snippet sing
	function ${1:Singleton} (${2:argument}) {
		// the cached instance
		var instance;

		// rewrite the constructor
		$1 = function $1($2) {
			return instance;
		};

		// carry over the prototype properties
		$1.prototype = this;

		// the instance
		instance = new $1();

		// reset the constructor pointer
		instance.constructor = $1;

		${0}

		return instance;
	}
# Crockford's object function
snippet obj
	function object(o) {
		function F() {}
		F.prototype = o;
		return new F();
	}
# Define multiple properties
snippet props
	var ${1:my_object} = Object.defineProperties(
		${2:new Object()},
		{
			${3:property} : {
				get : function $1_$3_getter() {
					// getter code
				},
				set : function $1_$3_setter(value) {
					// setter code
				},
				value        : ${4:value},
				writeable    : ${5:boolean},
				enumerable   : ${6:boolean},
				configurable : ${0:boolean}
			}
		}
	);
# Define single property
snippet prop
	Object.defineProperty(
		${1:object},
		'${2:property}',
		{
			get : function $1_$2_getter() {
				// getter code
			},
			set : function $1_$2_setter(value) {
				// setter code
			},
			value        : ${3:value},
			writeable    : ${4:boolean},
			enumerable   : ${5:boolean},
			configurable : ${0:boolean}
		}
	);

# Documentation

# docstring
snippet /**
	/**
	 * ${0:description}
	 *
	 */
snippet @par
	@param {${1:type}} ${2:name} ${0:description}
snippet @ret
	@return {${1:type}} ${0:description}
# JSON

# JSON.parse
snippet jsonp
	JSON.parse(${0:jstr});
# JSON.stringify
snippet jsons
	JSON.stringify(${0:object});

# DOM selectors

# Get elements
snippet get
	getElementsBy${1:TagName}('${0}')
# Get element
snippet gett
	getElementBy${1:Id}('${0}')
# Elements by class
snippet by.
	${1:document}.getElementsByClassName('${0:class}')
# Element by ID
snippet by#
	${1:document}.getElementById('${0:element ID}')
# Query selector
snippet qs
	${1:document}.querySelector('${0:CSS selector}')
# Query selector all
snippet qsa
	${1:document}.querySelectorAll('${0:CSS selector}')

# Debugging
snippet de
	debugger;
# console.log
snippet cl
	console.log(${0});
# console.debug
snippet cd
	console.debug(${0});
# console.err
snippet ce
	console.err(${0});
# console.trace
snippet ct
	console.trace(${0:label});
# console.time
snippet ctime
	console.time(${0:label});
# console.assert
snippet ca
	console.assert(${1:expression}, ${0:obj});
# console.dir
snippet cdir
	console.dir(${0:obj});

# Misc

# 'use strict';
snippet us
	'use strict';

# setTimeout function
snippet timeout
	setTimeout(function () {${0}}${2}, ${1:10});
